import SingleLoading from '@/utils/SingleLoading';
import Storage from '@/utils/storage';
import axios from 'axios';
import { ElMessage } from 'element-plus';
import { router } from '../../router';
import { refreshToken, logout, expires } from '@/api/login'
import { useUserStore } from '@/store/user';



let isInvalid = false

const pending = []
const { CancelToken } = axios
const removePending = ( config ) => {
  for ( const p in pending ) {
    if ( pending[p].u === `${config.url + JSON.stringify( config.data )}&${config.method}` ) {
      pending[p].f()
      pending.splice( p, 1 )
    }
  }
}

export const reqResolve = ( config ) => {
  if ( config.showLoading ) { SingleLoading.show() }
  // 如果是oauth接口，那么不需要加token
  if ( !config.url.includes( 'auth/oauth' )) {
    const token = Storage.get( 'token' );
    if ( token ) {
      config.headers['Authorization'] = `Bearer ${token}`;
      // config.headers['uid'] = '16'
    }
  }
  return config
}

export const reqReject = ( error ) => {
  return Promise.reject( error )
}

// 该数组中的错误不会展示错误弹窗，而且会返回resolve的res
const noMsgCode = [
  '002029',
  '002027',
  '002028',
  '800012',
  '800010',
  '910001',
  '002033'
]
// 刷新token的标志
let timeout
export const resResolve = () => {
  return async ( res ) => {
    const token = Storage.get( 'token' )
    if ( isInvalid ) return res?.data ?? res
    const { config } = res
    // 登录失效直接跳到login
    if ( '910001' === res.data.code ) {
      isInvalid = true
      if ( token ) {
        await logout({ accessToken: token })
        if ( config.showLoading ) { SingleLoading.hide() }
        Storage.remove( 'token' )
        Storage.remove( 'user' )
      }
      // logOut之后重置标识
      // 携带跳转之前的信息
      router.push({ path: '/login', query: { redirect: router.currentRoute.value.fullPath } })
      ElMessage.error( '登录过期,请重新登陆' )
      isInvalid = false
      return res
    }

    // 和认证相关的不做刷新token处理
    if ( !config.url.includes( 'auth/oauth' )) {
      if ( timeout ) { clearTimeout( timeout ) }
      let timeRemains = null
      // 用户停止操作界面1秒之后检查token过期
      timeout = setTimeout( async () => {
        try {
          timeRemains = await expires({ accessToken: Storage.get( 'token' ) })
          // 不足900秒请求新token
          if ( 900 > timeRemains.data ) {
            const { data } = await refreshToken({ accessToken: Storage.get( 'token' ) })
            // const userStore = useUserStore()
            // userStore.SET_TOKEN( data.access_token )
            // userStore.SET_USER( data )
            Storage.set( 'token', data.access_token )
            Storage.set( 'user', data )
            timeRemains = null
          }
        } catch ( e ) {
          console.log( '获取token出错' );
          console.log( e );
          timeRemains = null
        }
        timeout = null
        Storage.remove( 'TIME_OUT' )
      }, 1000 )
      Storage.set( 'TIME_OUT', timeout )
    }

    // 有code，同时status为false,
    // 有一些code不应该弹窗
    if ( res.data && !noMsgCode.includes( res.data.code ) && false === res.data.status ) {
      // 防止多次报错的标志
      isInvalid = true
      setTimeout(() => {
        ElMessage.error( res.data.msg || '抱歉，请稍后再试' )
        isInvalid = false
      })
    }
    await SingleLoading.hide()
    // 一般的状态错误返回reject的promise（数组外的）
    // console.log( res )
    if ( false === res.data.status && !noMsgCode.includes( res.data.code ) && !config.url.includes( 'captcha' )) return Promise.reject( res )
    return res?.data ?? res
  }
}

// 防止多次报错
let awaits = false
export const resReject = ( error ) => {
  // 进来就要判断awaits ，不然剩余请求进来之后会执行代码
  
  if ( awaits ) return error
  const { config, response } = error
  const url = config?.url
  // 如果oauth相关接口报错那么直接跳到login
  if ( url?.includes( 'oauth' )) {
    router.replace({ path: '/login' })
    Storage.remove( 'token' )
    Storage.remove( 'user' )
    return error
  }

  if ( '910001' === response?.data?.code ) {
    awaits = true
    logout({ accessToken: Storage.get( 'token' ) }).then(() => {
      SingleLoading.hide()
      Storage.remove( 'token' )
      Storage.remove( 'user' )
      // 携带跳转之前的信息
      router.push({ path: '/login', query: { redirect: router.currentRoute.value.fullPath } })
      awaits = false
      ElMessage.error( '登录过期,请重新登陆' )
    }).catch(( e ) => {
      console.log( e );
      // 有可能会进入catch
      router.push({ path: '/login', query: { redirect: router.currentRoute.value.fullPath } })
      SingleLoading.hide()
      awaits = false
    })
    return
  }


  awaits = true
  setTimeout(() => {
    ElMessage.error( response?.data?.msg || '抱歉，请稍后再试' )
    SingleLoading.hide()
    awaits = false
  }, 200 )
  if ( 'AxiosError' === error.name ) {
    return Promise.reject( error )
  }
  return error
}
